package com.cw.spider.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;

/**
 * 描述:
 *
 * @author withqianqian@163.com
 * @create 2020-08-28 9:07
 */
@Component
public class IPPool {


    volatile static List<JSONObject> pool;
    volatile static Map<String, JSONObject> availablePool = Maps.newConcurrentMap();
    @Value("${proxy.enable}")
    private boolean proxyEnable;
    @PostConstruct
    public List<JSONObject> init() {
        if (!proxyEnable)
            return null;
        if (pool != null && !pool.isEmpty())
            return Lists.newArrayList();
        RequestConfig defaultConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build();
        CloseableHttpClient httpClient = HttpClients.custom()
                .setDefaultRequestConfig(defaultConfig)
                .build();
        CloseableHttpResponse response = null;
        try {
            HttpGet httpGet = new HttpGet("http://proxylist.fatezero.org/proxy.list");
            response = httpClient.execute(httpGet);
            HttpEntity httpEntity = response.getEntity();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpEntity.getContent()));
            StringBuilder sb = new StringBuilder();
            sb.append("[");
            while (bufferedReader.ready()) {
                sb.append(bufferedReader.readLine() + ",");
            }
            sb.append("]");
            List<JSONObject> list = JSONArray.parseArray(sb.toString()).toJavaList(JSONObject.class);
            list = list.stream()
                    .filter(jsonObject -> "http".equals(jsonObject.getString("type")))
                    .collect(Collectors.toList());
            pool = list;
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return pool;
    }

    public static JSONObject random() {
        if (pool == null)
            return null;
        JSONObject ip;
        Random random = new Random();
        while (true) {
            if (pool.isEmpty()) {
                resetPool();
            }
            ip = pool.get(random.nextInt(pool.size()));
            RequestConfig defaultConfig = RequestConfig
                    .custom()
                    .setConnectTimeout(1500)
                    .setSocketTimeout(1500)
                    .setProxy(new HttpHost(ip.getString("host"), ip.getIntValue("port")))
                    .setCookieSpec(CookieSpecs.STANDARD).build();
            CloseableHttpClient httpClient = HttpClients.custom()
                    .setDefaultRequestConfig(defaultConfig)
                    .build();

            CloseableHttpResponse response = null;
            HttpGet httpGet = new HttpGet("http://www.baidu.com");
            httpGet.setHeader("User-Agent", "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.43 Safari/537.31");
            try {
                response = httpClient.execute(httpGet);
                if (response.getStatusLine().getStatusCode() < 300) {
                    return ip;
                } else {
                    pool.remove(ip);
                }
            } catch (IOException e) {
//                 System.out.println("Read timed out");
                pool.remove(ip);
            }
        }


    }

    public static void remove(JSONObject ip) {
        pool.remove(ip);
        availablePool.remove(ip.getString("host"));
    }

    public static void push(JSONObject ip) {
        availablePool.put(ip.getString("host"), ip);
    }

    public static JSONObject get() {
        if (!availablePool.isEmpty()) {
            String host = (String) availablePool.keySet().toArray()[0];
            JSONObject ip = availablePool.get(host);
            return ip;
        } else {
            return random();
        }

    }




    public static void resetPool() {
        RequestConfig defaultConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build();
        CloseableHttpClient httpClient = HttpClients.custom()
                .setDefaultRequestConfig(defaultConfig)
                .build();
        CloseableHttpResponse response = null;
        try {
            HttpGet httpGet = new HttpGet("http://proxylist.fatezero.org/proxy.list");
            response = httpClient.execute(httpGet);
            HttpEntity httpEntity = response.getEntity();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpEntity.getContent()));
            StringBuilder sb = new StringBuilder();
            sb.append("[");
            while (bufferedReader.ready()) {
                sb.append(bufferedReader.readLine() + ",");
            }
            sb.append("]");
            List<JSONObject> list = JSONArray.parseArray(sb.toString()).toJavaList(JSONObject.class);
            list = list.stream()
                    .filter(jsonObject -> "http".equals(jsonObject.getString("type")))
                    .collect(Collectors.toList());
            pool = list;
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
